package com.lhl.jwt.filter;

import com.lhl.jwt.domain.dto.WxLoginResultDTO;
import com.lhl.jwt.excepiton.ParamException;
import com.lhl.jwt.excepiton.WxException;
import com.lhl.jwt.token.WxAuthenticationToken;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @className: com.lhl.jwt.filter.WxAppletAuthenticationFilter
 * @description: 用于用户认证的filter，但是真正的认证逻辑会委托给
 * @author: king
 * @date: 2020-11-17
 **/
@Api(tags = "WxAppletAuthenticationFilter", produces = "")
@Slf4j
public class WxAppletAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.appsecret}")
    private String appsrcret;

    private String wxAuthUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";

    @Autowired
    private RestTemplate restTemplate;

    public WxAppletAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
        String code = httpServletRequest.getParameter("code");
        if(StringUtils.isBlank(code)){
            log.error("code is null");
            throw new ParamException("code is null");
        }
        String rawData = httpServletRequest.getParameter("rawData");
        if(StringUtils.isBlank(rawData)){
            log.error("rawData is null");
            throw new ParamException("rawData is null");
        }
        String signature = httpServletRequest.getParameter("signature");
        if(StringUtils.isBlank(signature)){
            log.error("signature is null");
            throw new ParamException("signature is null");
        }
        String url = String.format(wxAuthUrl, appid, appsrcret, code);
        log.debug("wx auth url: [{}]", url);
        WxLoginResultDTO wxLoginResult = restTemplate.getForObject(url, WxLoginResultDTO.class);
        if(wxLoginResult.getErrcode() != null && !wxLoginResult.getErrcode().equals(0)){
            log.error("wx auth failed, errCode is [{}], errMsg is [{}]", wxLoginResult.getErrcode(), wxLoginResult.getErrmsg());
            throw new WxException("微信登入异常");
        }
        log.info("wx login result: [{}]", wxLoginResult);
        return this.getAuthenticationManager().authenticate(new WxAuthenticationToken(wxLoginResult.getOpenid(), wxLoginResult.getSession_key(), rawData, signature));
    }
}
